import {
  HttpException,
  HttpStatus,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { InRecord, Prisma } from '@prisma/client';
import { PrismaService } from 'src/db/prisma.service';
import { GoodsService } from 'src/goods/goods.service';
import { requestPromise } from 'src/interface';
import * as dayjs from 'dayjs';
@Injectable()
export class InRecordService {
  constructor(
    private prisma: PrismaService,
    private readonly goodsService: GoodsService,
  ) {}

  async findOne(
    InRecordWhereUniqueInput: Prisma.InRecordWhereUniqueInput,
  ): Promise<InRecord | null> {
    return this.prisma.inRecord.findUnique({
      where: {
        id: +InRecordWhereUniqueInput.id,
      },
    });
  }

  async findAll(params: {
    pageNum?: number;
    pageSize?: number;
    cursor?: Prisma.InRecordWhereUniqueInput;
    outBoundNo?: string;
    type?: number;
    createAt?: Date;
    orderBy?: Prisma.InRecordOrderByWithRelationInput;
  }): Promise<requestPromise> {
    const {
      pageNum = 1,
      pageSize = 10,
      cursor,
      orderBy,
      outBoundNo,
      type,
      createAt,
    } = params;
    const createAtTime = {
      gte: new Date(createAt[0]),
      lte: new Date(createAt[1]),
    };
    console.log(params, 'params', createAt);
    let where = {
      outBoundNo,
      type,
    };
    if (createAt[0] && createAt[1]) {
      where['createAt'] = createAtTime;
    }
    const totalInRecordCount = await this.prisma.inRecord.count({
      where,
    });
    const InRecords = await this.prisma.inRecord.findMany({
      skip: (pageNum - 1) * pageSize,
      take: pageSize,
      cursor,
      where,
      orderBy,
      select: {
        id: true,
        remark: true,
        outBoundNo: true,
        supplierId: true,
        type: true,
        createAt: true,
        InGoods: {
          select: {
            id: true,
            goodName: true,
            goodId: true,
            Sku: true,
          },
        },
      },
    });
    return {
      code: 200,
      message: 'success',
      data: {
        list: InRecords,
        total: totalInRecordCount,
      },
    };
  }
  async create(data): Promise<InRecord> {
    console.log(data, 'data');
    let { supplierId, creator, InGoods, type, remark } = data;
    let time = new Date();
    let outBoundNo = dayjs(time).format('[No]YYYYMMDDHHmmss');
    let inGoodsData = [];
    InGoods.map(async (element) => {
      let itemObj = {
        goodId: element.goodId,
        goodName: element.goodName,
        Sku: element.Sku,
      };
      inGoodsData.push(itemObj);
    });
    try {
      let saveData = {
        supplierId: supplierId,
        type,
        outBoundNo,
        creatorId: creator,
        remark: remark,
        InGoods: {
          create: inGoodsData,
        },
      };
      return this.prisma.$transaction(async (prisma) => {
        let men = '';
        //10进货 //20出货 // 30日常销售 //40退货 //50 损耗
        if (type == 20 || type == 30 || type == 50) {
          men = 'decrement';
        } else {
          men = 'increment';
        }
        if (inGoodsData.length > 0) {
          await Promise.all(
            inGoodsData.map(async (sku) => {
              sku.Sku.map(async (it) => {
                console.log(it, 'it');
                await prisma.sku.update({
                  where: { id: it.id },
                  data: {
                    quantity: {
                      [men]: it.quantity,
                    },
                  },
                });
              });
            }),
          );
        }
        let result = await this.prisma.inRecord.create({
          data: saveData,
        });
        return result;
      });
    } catch (e) {
      console.log(e, 'e');
      throw new HttpException(e.response.message, HttpStatus.BAD_REQUEST);
    }
  }

  async update(params: { where; data }): Promise<InRecord> {
    console.log(params, 'params');
    const { where, data } = params;
    let { supplierId, creator, InGoods, type, remark } = data;
    let updateMany = [];
    let createMany = [];
    let createManyInGoods = [];
    let updateManyInGoods = [];
    console.log('InGoods', InGoods);
    let allInGoodsIds = await this.prisma.inGoods.findMany({
      where: {
        orderId: where.id,
      },
      select: { id: true },
    });
    let updateIds = [];
    InGoods = InGoods.map((item) => {
      updateIds.push(item.id);
      return item;
    });
    let deleteGoods = allInGoodsIds.filter((item) => {
      return !updateIds.includes(item.id);
    });
    console.log('allInGoodsIds', deleteGoods, InGoods);
    if (deleteGoods.length > 0) {
      let deletGoods = await Promise.all(
        deleteGoods.map((item) => {
          this.prisma.inGoods.delete({ where: { id: item.id } });
        }),
      );
      console.log('deletGoods', deletGoods);
    }
    InGoods.map((item) => {
      item.Sku.map((it) => {
        if (item.id > 0) {
          updateMany.push(it);
          updateManyInGoods.push(item);
        } else {
          createManyInGoods.push(item);
          console.log(it, 'it');
          createMany.push(it);
        }
      });
    });
    let updateData = {
      supplierId: supplierId,
      type,
      creatorId: creator,
      remark: remark,
      InGoods: {
        ...(createManyInGoods && { create: createManyInGoods }),
        ...(updateManyInGoods && {
          update: [
            ...updateManyInGoods.map((update) => ({
              where: { id: update.id },
              data: {
                Sku: update.Sku,
              },
            })),
          ],
        }),
      },
    };
    if (createMany.length > 0) {
      this.AddGoods(createMany, type);
    } else {
      this.updateGoods(InGoods, updateMany, type, where.id);
    }
    console.log(
      'createMany',
      createMany,
      'createManyInGoods',
      createManyInGoods,
      'updateMany',
      updateMany,
      'updateManyInGoods',
      updateManyInGoods,
    );
    try {
      console.log('updateData', updateData);
      let c = await this.prisma.inRecord.update({
        data: {
          supplierId: updateData.supplierId,
          type: updateData.type,
          remark: updateData.remark,
          InGoods: updateData.InGoods,
        },
        where,
      });
      return c;
    } catch (err) {
      console.log('err', err);
    }
  }

  async deleteOrderWithProducts(id) {
    const deleteOrder = this.prisma.inRecord.delete({
      where: {
        id,
      },
    });
    const deleteInGoods = this.prisma.inGoods.deleteMany({
      where: {
        orderId: id,
      },
    });
    return this.prisma.$transaction([deleteInGoods, deleteOrder]);
  }
  async delete(where: Prisma.InRecordWhereUniqueInput): Promise<any> {
    this.deleteOrderWithProducts(+where.id)
      .then((res) => {
        console.log('订单和关联的商品已成功删除', res);
      })
      .catch((error) => {
        console.error('删除订单和商品时出错：', error);
      })
      .finally(async () => {
        await this.prisma.$disconnect();
      });
  }
  // 新增 删除，创建 商品数据回滚
  // 如果是删除 则商品所有数量全部还原
  // 如果是新增 则商品数量添加
  // 如果是修改则 按照数量加减
  async AddGoods(InGoods, type) {
    console.log('AddGoods', InGoods);
    await Promise.all(
      InGoods.map(async (product) => {
        let men = '';
        //10进货 //20出货 // 30日常销售 //40退货 //50 损耗
        if (type == 20 || type == 30 || type == 50) {
          men = 'decrement';
        } else {
          men = 'increment';
        }
        try {
          const updatedProduct = await this.prisma.sku.update({
            where: { id: product.id },
            data: {
              quantity: {
                [men]: Math.floor(product.quantity),
              },
            },
          });
          console.log('updatedProduct', updatedProduct);
          return updatedProduct;
        }catch(err){
          console.log('err',err);
        }
      }),
    );
  }
  async updateGoods(InGoods, updateSku, type, orderId) {
    let allGoods = await this.prisma.inGoods.findMany({ where: { orderId } });
    console.log(allGoods, 'allGoods');
    let updateIds = [];
    InGoods = InGoods.map((item) => {
      updateIds.push(item.id);
      return item;
    });
    console.log(InGoods, 'InGoods');

    let deleteGoods = allGoods.filter((item) => {
      return !updateIds.includes(item.id);
    });
    if (deleteGoods.length > 0) {
      console.log('deleteGoods', deleteGoods);
      this.deletGoods(deleteGoods, type);
    }
    console.log(deleteGoods, 'deleteGoods', updateIds, InGoods);
    await Promise.all(
      updateSku.map(async (product) => {
        let men = '';
        //10进货 //20出货 // 30日常销售 //40退货 //50 损耗
        if (product.num == 0) {
          return;
        }
        if (type == 20 || type == 30 || type == 50) {
          //减
          if (product.num > 0) {
            men = 'decrement'; //减
          } else {
            men = 'increment'; //加
          }
        } else {
          //加
          if (product.num > 0) {
            men = 'increment'; //加
          } else {
            men = 'decrement'; //减
          }
        }
        console.log('product.num', product.num, men);
        const updatedProduct = await this.prisma.sku.update({
          where: { id: product.id },
          data: {
            quantity: {
              [men]: Math.abs(product.num),
            },
          },
        });
        return updatedProduct;
      }),
    );
  }
  async deletGoods(InGoods, type) {
    let ids = [];
    await Promise.all(
      InGoods.map(async (product) => {
        ids.push(product.id);
        let c = await this.goodsService.findOne({ id: product.goodId });
        console.log(c, 'c');
        if (!c) {
          throw new NotFoundException(`id:${product.goodId}商品不存在`);
        }
        let men = '';
        //10进货 //20出货 // 30日常销售 //40退货 //50 损耗
        if (type == 20 || type == 30 || type == 50) {
          men = 'increment';
        } else {
          men = 'decrement';
        }
        const deleteGood = await this.prisma.inGoods.delete({
          where: {
            id: product.id,
          },
        });
        console.log('deleteGood', deleteGood);
        deleteGood.Sku = JSON.parse(JSON.stringify(deleteGood.Sku));
        if (Array.isArray(deleteGood.Sku)) {
          deleteGood.Sku.map(async (ite: { id: string; quantity: string }) => {
            let c = await this.prisma.sku.update({
              where: { id: Number(ite.id) },
              data: {
                quantity: {
                  [men]: Number(ite.quantity),
                },
              },
            });
            console.log(c, 'c');
          });
        }
      }),
    );
  }
}
